处理 Events

使用 React element 处理事件非常类似于 DOM 元素处理事件。只是语法略有不同:

  • React 事件命名使用小驼峰,而不是小写。
  • 通过 JSX 传递一个函数作为时间处理者,而不是字符串。

例如,HTML中:

<button onclick="activateLasers()">
  Activate Lasers
</button>

React 中略有不同:

<button onClick={activateLasers}>
  Activate Lasers
</button>

另一个不同是在 React 中不能通过返回 false 来阻止默认行为。必须明确调用 preventDefault。例如,普通 HTML 阻止默认链接打开一个新页面的行为,你可以写:

<a href="#" onclick="console.log('The link was clicked.'); return false">
  Click me
</a>

React 中,替代方法为:

function ActionLink() {
  function handleClick(e) {
    e.preventDefault();
    console.log('The link was clicked.');
  }
  
  return (
    <a href="#" onClick={handleClick}>
      Click me
    </a>
  );
}

这里, e 是一个合成事件。 React 根据 WEC spec定义这些合成事件, 所以不需要担心跨浏览器兼容问题。 点击SyntheticEvent 参考指导查看更多.

使用 React 你通常不需要调用 addEventListener 来给你一个已创建的 DOM 元素添加监听器。 相反,只在元素初始化渲染的时候提供监听器。

使用 [ES6 class]()定义一个组件,一个常见模式是类中一个方法为一个事件处理者.例如, Toggle 组件渲染一个按钮让用户在 "ON" 和 "OFF" 中切换:

class Toggle extends React.Component {
  constructor(props) {
    super(props);
    this.state = {isToggleOn: true};
    this.handleClick = this.handleClick.bind(this);
  }
   
  handleClick() {
    this.setState(prevState => ({
      isToggleOn: !prevState.isToggleOn
    }));
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        {this.state.isToggleOn ? 'ON' : 'OFF' }
      </button>
    );
  }
}

ReactDOM.render(
  <Toggle />,
  document.getElementById('root')
);

[在线尝试]()

一定要小心 JSX 回调中 this 的含义。在 JavaScript 中, 类方法默认不[绑定]()。如果忘记绑定 this.handleClick 传递它给 onClick, this 在函数实际调用的时候会变成 undefined.

这不是 React 特殊行为;是 [JavaScript 中函数如何运作]()。通常,你引用一个方法后面不带 () 。例如, onClick={this.handleClick}, 你应该绑定这个方法。

如果 bind(绑定)让你很烦,两种方式可以处理。如果你使用实验性的 [public class fields syntax(公开类字段语法)](),你可以用类字典去正确的绑定回调:

class LoggingButton extends React.Component {
  // 这个预发确保 'this' 通过 handleClick 绑定。
  // 警告:这个是 *experimental(实验性)* 语法。
  handleClick = () => {
    console.log('this is:', this);
  }
  
  render() {
    return (
      <button onClick={this.handleClick}>
        Click me
      </button>
    );
  }
}

这个预发在 Create React App 默认启用。

如果你不使用类字段语法,你可以在回调中使用 [箭头函数]():

  handleClick() {
    console.log('this is:', this);
  }

  render() {
    // 语法确保 'this' 通过绑定 handleClick 
    return (
      <button onClick={(e) => this.handleClick(e)}>
        Click me
      </button>
    );
  }
}

问题在于这个语法 LoggingButton 每次渲染创建一个不同的回调。大多数情景,情况还好。
然而,如果回调是将一个底层组件作为 props 被传递。这些组件可能做额外的重渲染。通常我们建议在构造器中使用类字段语法绑定来避免这类性能问题。

给事件处理者传递参数

循环内部通常想要传递额外的参数给一个事件处理者。例如,如果 id 是行 ID, 下面两种都可以:

<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>

上面两行是等效的, 分别使用 [箭头函数]() 和 [Function.prototype.bind(函数原型链绑定)]()。

两种场景呈现 React 事件的 e 参数都会作为 ID 之后的第二餐宿传递。使用箭头函数,必须显式传递,使用 bind 任意多参数会自动指向。

[下一部分 条件渲染]()


yich_chia
8 声望3 粉丝